package com.jintian.smart.kernel.common.orm;

import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.nio.charset.StandardCharsets;

public class RestResultWrapperReturnValueHandler implements HandlerMethodReturnValueHandler {
    @Autowired
    private RestResultResponseBodyAdvice restResultResponseBodyAdvice;

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        return restResultResponseBodyAdvice.supports(returnType, null);
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest) throws Exception {
        Assert.isTrue(!mavContainer.isRequestHandled(), "method return value has'nt handled");
        HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
        if (response.isCommitted()) {
            return;
        }
        mavContainer.setRequestHandled(true);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        Object obj = restResultResponseBodyAdvice.beforeBodyWrite(returnValue, returnType, MediaType.APPLICATION_JSON,
                null, webRequest.getNativeRequest(ServerHttpRequest.class),
                webRequest.getNativeResponse(ServerHttpResponse.class));
        if (returnType.getMethod().getReturnType().equals(String.class) && obj instanceof String) {
            response.setContentType(MediaType.TEXT_PLAIN_VALUE);
            response.getOutputStream().write(obj.toString().getBytes(StandardCharsets.UTF_8));
        } else {
            response.getOutputStream().write(restResultResponseBodyAdvice.objectMapper.writeValueAsBytes(obj));
        }
    }
}
